package org.mvnlifeclycle;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

/**
 *
 * @goal yaml2mojo
 * 
 */
public class Ymal2Mojo
    extends AbstractMojo
{		
	/**
	 * @parameter default-value="src/main/build/packaging"
	 */
	protected File packagingFileDirectory;
	
	/**
	 * @parameter default-value="src/main/build/goal"
	 */
	protected File goalFileDirectory;
	
		
	/**
	 * @parameter default-value="${project.build.directory}/generated-sources"
	 */
	protected File outputDirectory;
	
	/**
	 * @parameter default-value="${project.build.outputDirectory}"
	 */
	protected File buildOutputDirectory;
	
	/**
	 * @parameter default-value="org.mvnlifecycle"
	 */
	protected String mojoGroupId;
	
	/**
	 * @parameter default-value="${project.artifactId}"
	 */
	protected String mojoArtifactId;
	

    public void execute()
        throws MojoExecutionException
    {
    	try{
    		List<Process> processes = new ArrayList<Process>();
    		
    		if(goalFileDirectory != null && goalFileDirectory.exists()){
    			getLog().info(goalFileDirectory.getAbsolutePath());
    			Collection<File> listFiles = FileUtils.listFiles(goalFileDirectory, new String[]{"yml", "yaml"}, true);
    			for (File processFile : listFiles) {
					getLog().info("Found goal definition file: " + processFile.getName());
					processes.add(buildProcessWithMojos(processFile));
				}
    		}

    		if(packagingFileDirectory != null  && packagingFileDirectory.exists()){
    			getLog().info(packagingFileDirectory.getAbsolutePath());
    			Collection<File> listFiles = FileUtils.listFiles(packagingFileDirectory, new String[]{"yml", "yaml"}, true);
    			for (File processFile : listFiles) {
					getLog().info("Found packaging definition file: " + processFile.getName());
					processes.add(buildProcessWithMojos(processFile));
				}
    		}
    		
    		if(processes.isEmpty()){
    			getLog().warn("couldn't find process files");
    		}
    		
    		buildComponentXml(processes);
    		
    	}catch(Exception exc){
    		throw new MojoExecutionException(exc.getMessage(), exc);
    	}
    }

	private void buildComponentXml(List<Process> processes) throws Exception{
		if(processes.isEmpty()){
			return;
		}
		
    	VelocityTemplateWriter templateWriter = new VelocityTemplateWriter("components.xml.vm");

    	File pathWithFile = new File(buildOutputDirectory, "META-INF/plexus/components.xml");
		getLog().info("Writing file: " + pathWithFile.getAbsolutePath());
    	templateWriter.write(processes, pathWithFile);
    	
    	
	}

	private Process buildProcessWithMojos(File processFileArg) throws Exception {
		YamlProcessReader processReader = new YamlProcessReader(mojoGroupId, mojoArtifactId);
		Process process = processReader.readFromFile(processFileArg);
    	VelocityTemplateWriter templateWriter = new VelocityTemplateWriter("mojo.vm");
    	
    	if(process.standaloneMojo != null){
			File pathWithFile = new File(outputDirectory, convertToFilePath(mojoGroupId, process.standaloneMojo.className));
			getLog().info("Writing file: " + pathWithFile.getAbsolutePath());
			templateWriter.write(process.standaloneMojo, pathWithFile);
    	}else{
	    	for (Phase phase : process.phases) {
	    		for (MojoModel mojo : phase.mojos) {
	    			File pathWithFile = new File(outputDirectory, convertToFilePath(mojoGroupId, mojo.className));
	    			getLog().info("Writing file: " + pathWithFile.getAbsolutePath());
	    			templateWriter.write(mojo, pathWithFile);
	    		}
	    	}
    	}
    	
    	return process;
	}

	private String convertToFilePath(String packageName2, String className) {
		return StringUtils.replace(packageName2, ".", "/") + "/" + className +".java";
	}
    
    public static void main(String[] args) throws Exception {

		Ymal2Mojo ymal2Mojo = new Ymal2Mojo();
		ymal2Mojo.mojoGroupId = "test";
		ymal2Mojo.goalFileDirectory = new File("src/test/resources/build/goal");
		ymal2Mojo.packagingFileDirectory = new File("src/test/resources/build/packaging");
		ymal2Mojo.outputDirectory = new File("./test");
		ymal2Mojo.execute();
    }
}
